/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package maquinaPila;

import instruccion.Instruccion;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;
import java.util.StringTokenizer;
import javax.swing.JOptionPane;

/**
 *
 * @author Abel
 */
public class MaquinaPila {
    // Memoria principal con celdas direccionables con datos
    private Map<Integer, Float> memoria;
    // Memoria de programa con celdas direccionables con instrucciones 
    private ArrayList<Instruccion> prog;
    // Contador de programa con un registro para la dirección de la instrucción actualmente en ejecución
    private int cProg;
    // Pila de datos con celdas direccionables con datos
    private Stack<Float> pila;
    // Cima de la pila de datos con un registro para la dirección del dato situado actualmente en la cima de la pila
    private int cPila;
    // Registro con un bit de parada que detiene la ejecución
    private boolean p;
    // Registro con un bit de de swap1, valdrá 1 si debemos invertir las operaciones de suma y resta y 0 en caso contrario
    private boolean ss;
    // Registro con un bit de de swap2, valdrá 1 si debemos invertir las operaciones de multiplicación  y división  y 0 en caso contrario
    private boolean sm;
    // Registro con un bit de error de división por cero en ejecución que detiene la ejecución
    private boolean errorByZero;
    // Registro con un bit de error de lectura en ejecución que detiene la ejecución
    private boolean errorLectura;
    
    public MaquinaPila(){
        // Inicializamos todo
        prog = new ArrayList<Instruccion>();
        pila = new Stack<Float>();
        cProg = 0;
        cPila = -1;
        memoria = new HashMap<Integer, Float>();
        p = ss = sm = errorByZero = errorLectura = false;
        // Inicializamos CP y B antes de declarar las varibales globales
        memoria.put(0,(float)2.0);
        memoria.put(1,(float)2.0);
    }
    
    public void cargaCodigoPrograma(ArrayList<Instruccion> cod){
        Iterator<Instruccion> it = cod.iterator();
        while(it.hasNext()){
            prog.add(it.next());
        }
    }
    
    public void ejecutaCodigo(){
        // Ponemos parada a false
        p = false;

        while(!p && !errorByZero && !errorLectura){
            // Cogemos de memoria la instrucción a la que apunte el contador de programa
            String cod = prog.get(cProg).getCod();

            //Tokeniza cada funcion por "("
            StringTokenizer tokensInstr = new StringTokenizer(cod,"(");

            String nombreFuncion = tokensInstr.nextToken();

            // Vemos que debemos hacer en nuestra maquina a pila
            if(nombreFuncion.equals("copia")){
                // Llamamos a la funcion que realizará la copia
                copia();

            }else if(nombreFuncion.equals("apila")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                // Cogemos los parametros de la instruccion
                StringTokenizer parametros = new StringTokenizer(resto,")");
                String v = parametros.nextToken();

                float n = Float.parseFloat(v);
                apila(n);

            }else if(nombreFuncion.equals("apila_dir")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                // Cogemos los parametros de la instruccion
                StringTokenizer parametros = new StringTokenizer(resto,")");
                int n = Integer.parseInt(parametros.nextToken());
                // Llamamos a la funcion de apilar
                apila_dir(n);

            }else if(nombreFuncion.equals("apila_ind")){
                // Llamamos a la funcion de apila_ind
                apila_ind();

            }else if(nombreFuncion.equals("desapila")){
                // Llamamos a la funcion de apila_ind
                desapila();

            }else if(nombreFuncion.equals("desapila_dir")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                // Cogemos los parametros de la instruccion
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Cogemos la direccion
                int dir = Integer.parseInt(parametros.nextToken());
                // Llamamos a la funcion de desapilar dada una direccion
                desapila_dir(dir);

            }else if(nombreFuncion.equals("desapila_ind")){
                // Llamamos a la funcion de desapilar en la direccion que hay en la cima de la pila lo que hay en la subcima
                desapila_ind();

            }else if(nombreFuncion.equals("leer")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Llamamos a la funcion que leera por consola
                lee(parametros.nextToken());

            }else if(nombreFuncion.equals("escribir")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Cogemos el tipo de la expresion a escribir
                String tipo = parametros.nextToken();
                // Llamamos a la funcion que escribira por consola
                escribe(tipo);

            }else if(nombreFuncion.equals("invierteS")){
                // Llamamos a la funcion que invierte el bit S
                invierteS();

            }else if(nombreFuncion.equals("invierteM")){
                // Llamamos a la funcion que invierte el bit M
                invierteM();

            }else if(nombreFuncion.equals("menorQue")){
                // Llamamos a la funcion que realiza la operacion menor
                menorQue();

            }else if(nombreFuncion.equals("mayorQue")){
                // Llamamos a la funcion que realiza la operacion mayor
                mayorQue();

            }else if(nombreFuncion.equals("menorIgualQue")){
                // Llamamos a la funcion que realiza la operacion menor o igual
                menorIgualQue();

            }else if(nombreFuncion.equals("mayorIgualQue")){
                // Llamamos a la funcion que realiza la operacion mayor o igual
                mayorIgualQue();

            }else if(nombreFuncion.equals("igual")){
                // Llamamos a la funcion que realiza la operacion igual
                igual();

            }else if(nombreFuncion.equals("distinto")){
                // Llamamos a la funcion que realiza la operacion distinto
                distinto();

            }else if(nombreFuncion.equals("suma")){
                // Llamamos a la funcion que realiza la operacion suma
                suma();

            }else if(nombreFuncion.equals("sumar")){
                // Llamamos a la funcion que realiza la operacion suma
                sumar();

            }else if(nombreFuncion.equals("resta")){
                // Llamamos a la funcion que realiza la operacion resta
                resta();

            }else if(nombreFuncion.equals("restar")){
                // Llamamos a la funcion que realiza la operacion resta
                restar();

            }else if(nombreFuncion.equals("oLogica")){
                // Llamamos a la funcion que realiza la operacion o Logica
                oLogica();

            }else if(nombreFuncion.equals("multiplicar")){
                // Llamamos a la funcion que realiza la operacion multiplicacion
                multiplicar();

            }else if(nombreFuncion.equals("multiplicacion")){
                // Llamamos a la funcion que realiza la operacion suma
                multiplicacion();

            }else if(nombreFuncion.equals("division")){
                // Llamamos a la funcion que realiza la operacion division
                division();

            }else if(nombreFuncion.equals("modulo")){
                // Llamamos a la funcion que realiza la operacion modulo
                modulo();

            }else if(nombreFuncion.equals("yLogica")){
                // Llamamos a la funcion que realiza la operacion y Logica
                yLogica();

            }else if(nombreFuncion.equals("desplazaDer")){
                // Llamamos a la funcion que realiza la operacion de desplazamiento a derecha
                desplazaDer();

            }else if(nombreFuncion.equals("desplazaIzq")){
                // Llamamos a la funcion que realiza la operacion de desplazamiento a izquierda
                desplazaIzq();

            }else if(nombreFuncion.equals("negacion")){
                // Llamamos a la funcion que realiza la operacion de negacion
                negacion();

            }else if(nombreFuncion.equals("menosUnario")){
                // Llamamos a la funcion que realiza la operacion de desplazamiento a menos unario
                menosUnario();

            }else if(nombreFuncion.equals("casting")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                // Cogemos los parametros de la instruccion
                StringTokenizer parametros = new StringTokenizer(resto,")");
                String tipo = parametros.nextToken();
                // Llamamos a la funcion que realiza la operacion de casting
                casting(tipo);
            }else if(nombreFuncion.equals("reservaMemoria")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Llamamos a la funcion que reservara la memoria
                reservaMemoria(Integer.parseInt(parametros.nextToken()));
            }else if(nombreFuncion.equals("ir_f")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Llamamos a la funcion que realizara el salto
                ir_f(Integer.parseInt(parametros.nextToken()));
            }else if(nombreFuncion.equals("ir_v")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Llamamos a la funcion que realizara el salto
                ir_v(Integer.parseInt(parametros.nextToken()));
            }else if(nombreFuncion.equals("ir_a")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Llamamos a la funcion que realizara el salto
                ir_a(Integer.parseInt(parametros.nextToken()));
            }else if(nombreFuncion.equals("ir_ind")){
                // Llamamos a la funcion que realizara el salto
                ir_ind();
            }else if(nombreFuncion.equals("stop")){
                // Llamamos a la funcion de parar
                stop();

            }else if(nombreFuncion.equals("mueve")){
                // Cogemos el resto de la instruccion
                String resto = tokensInstr.nextToken();
                StringTokenizer parametros = new StringTokenizer(resto,")");

                // Llamamos a la funcion que realizara el movimiento
                mueve(Integer.parseInt(parametros.nextToken()));
            }else{
                System.out.println("NO ENTIENDO: " + nombreFuncion);
                cProg++;
            }
        }
    }
    
    //Coloca un valor entero en la cima de la pila.
    public void copia() {
        float numero = pila.pop();
        pila.push(numero);
        pila.push(numero);
        cPila++;
        cProg++;
    }
    
    //Coloca un valor entero en la cima de la pila.
    public void apila(float numero) {
        pila.push(numero);
        cPila++;
        cProg++;
    }

    //Guarda en la cima de la pila el valor de la direccion de memoria.
    public void apila_dir(int direccion) {
        pila.push(memoria.get(direccion));
        cPila++;
        cProg++;
    }
    
    //Apila en la cima de la pila, el contenido de la direccion de memoria que haya en la cima
    public void apila_ind(){
        float dir = pila.pop();
        pila.push(memoria.get((int)dir));
        cProg++;
    }

    //Elimina lo que haya en la cima de la pila
    public void desapila() {
        pila.pop();
        cPila--;
        cProg++;
    }
    
    //Guarda en la dirección de memoria indicada el valor de la cima de la pila.
    public void desapila_dir(int direccion) {
        float num = pila.pop();
        memoria.put(direccion, num);
        cPila--;
        cProg++;
    }
    
    //Guarda en la dirección de memoria de la cima de la pila, el valor que hay en la subcima de la misma.
    public void desapila_ind() {
        float num = pila.pop();
        float dir = pila.pop();
        memoria.put((int)dir, num);
        cPila -= 2;
        cProg++;
    }

    //Indica el fin del código a pila. Se utiliza para saber cuando deber parar nuestra máquina virtual de ejecutar
    public void stop(){
        p = true;
        cProg++;
    }

    //Lee un dato de entrada y lo guarda en la dirección de memoria correspondiente.
    public void lee(String tipo){
        float dir = (float)pila.pop();
        int direccion = (int) dir;
        // Si es el tipo es natural o integer, hacemos una lectura sobre una variable de tipo int de java
        if(tipo.equals("natural") || tipo.equals("integer")){
            int aux = -1;
            //En caso de que no meta entero ni natural, salta al catch
            try{
                aux = Integer.parseInt(JOptionPane.showInputDialog("Ingrese numero"));
                if(aux != -1){
                    memoria.put(direccion, (float)aux);
                    if(tipo.equals("natural") && aux < 0){
                        System.out.println("ERROR: No se admite un número negativo como natural.");
                        errorLectura = true;
                    }
                }else{
                    errorLectura = true;
                    System.out.println("ERROR EN EJECUCION. Se esperaba un tipo natural o integer.");
                }
            }catch(Exception e){
                errorLectura = true;
                System.out.println("ERROR EN EJECUCION. Se esperaba un tipo natural o integer.");
            }			
        }else if(tipo.equals("boolean")){
            String introducido = null;
            introducido = JOptionPane.showInputDialog("Ingrese booleano (true/false)");
            if(introducido!= null && introducido.equals("true")){
                memoria.put(direccion, (float)1);
            }else if(introducido!= null && introducido.equals("false")){
                memoria.put(direccion, (float)0);
            }else{
                errorLectura = true;                
                System.out.println("ERROR EN EJECUCION. Se esperaba un tipo boolean (true o false).");
            }
        }else if(tipo.equals("character")){
            char aux = ' ';
            String introducido = null;
            introducido = JOptionPane.showInputDialog("Ingrese un caracter");
            if(introducido != null && introducido.length() < 3){
                if(introducido.length() == 2){
                    switch (introducido){
                        case "\\n": aux = '\n';
                                   break;
                        case "\\t": aux = '\t';
                                   break;
                        default:   errorLectura = true;
                                   System.out.println("ERROR EN EJECUCION. Se esperaba un caracter sin comillas. Tambien se adminten los caracteres especiales \\n y \\t.");
                                   break;
                    }
                }else{
                    aux = introducido.charAt(0);
                }
                memoria.put(direccion, (float)aux);			
            }else{
                errorLectura = true;
                System.out.println("ERROR EN EJECUCION. Se esperaba un caracter sin comillas. Tambien se adminten los caracteres especiales \\n y \\t.");
            }
        }else if(tipo.equals("float")){
            float aux;
            //En caso de que no meta float, salta al catch
            try{
                String introducido = null;
                introducido = JOptionPane.showInputDialog("Ingrese un número real");
                if(introducido != null){
                    aux = Float.parseFloat(introducido);
                    // Vemos que si tiene más de un decimal no acaba en 0
                    int num = introducido.length();
                    int i = 0; 
                    while(i<num && introducido.charAt(i) != '.'){
                            i++;
                    }
                    introducido = introducido.substring(i+1,num);
                    num = introducido.length();
                    if(num>1 && introducido.charAt(num-1) == '0'){
                        System.out.println("ERROR: No se admiten reales con más de un dígito en parte decimal, que acaben en 0");
                        errorLectura = true;
                    }else{
                        memoria.put(direccion, aux);
                    }
                }else{
                    errorLectura = true;
                    System.out.println("ERROR EN EJECUCION. Se esperaba un tipo float.");
                }
            }catch(Exception e){
                errorLectura = true;
                System.out.println("ERROR EN EJECUCION. Se esperaba un tipo float.");
            }
        }
        //No se modifica cPila porque mete un valor y luego lo quita
        cProg++;
        cPila--;
    }

    //Muestra por pantalla el valor que haya en la cima de la pila.
    public void escribe(String tipo){
        // Sacamos lo que haya en la cima
        float num = pila.pop();

        // Vemos el tipo de la expresion a mostrar
        if(tipo.equals("natural") || (tipo.equals("integer"))){
            int v = (int)num;
            System.out.println("Consola> " + v);
        }else if( tipo.equals("boolean") ){
            int b = (int)num;
            if(b == 1){
                System.out.println("Consola> true");
            }else if(b == 0){
                System.out.println("Consola> false");
            }
        }else if(tipo.equals("character")){
            char c = (char)num;
            System.out.println("Consola> " + c);
        }else if(tipo.equals("float")){
            System.out.println("Consola> " + num);
        }
        
        cPila--;
        cProg++;
    }

    //Invierte el valor del bit S para indicar que se ha producido un swap1()
    public void invierteS(){
        ss = !ss;
        cProg++;
    }

    //Invierte el valor del bit M para indicar que se ha producido un swap2()
    public void invierteM(){
        sm = !sm;
        cProg++;
    }

    //Compara si el elemento que hay bajo la cima de la pila es menor que el de la cima
    public void menorQue(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if(a < b){
            pila.push((float)1);
        }else{
            pila.push((float)0);
        }
        
        cPila--;
        cProg++;	
    }

    //Compara si el elemento que hay bajo la cima de la pila es mayor que el de la cima
    public void mayorQue(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();
        
        if(a > b){
            pila.push((float)1);
        }else{
            pila.push((float)0);
        }
        
        cPila--;
        cProg++;
    }

    //Compara si el elemento que hay bajo la cima de la pila es menor o igual que el de la cima
    public void menorIgualQue(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if(a <= b){			
            pila.push((float)1);
        }else{
            pila.push((float)0);
        }
        
        cPila--;
        cProg++;
    }

    //Compara si el elemento que hay bajo la cima de la pila es mayor o igual que el de la cima
    public void mayorIgualQue(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if(a >= b){
            pila.push((float)1);
        }else{
            pila.push((float)0);
        }
        
        cPila--;
        cProg++;
    }	

    //Compara si el elemento que hay bajo la cima de la pila es igual que el de la cima
    public void igual(){
        float b = pila.pop();
        float a = pila.pop();

        if(a == b){
            pila.push((float)1);
        }else{
            pila.push((float)0);
        }
                
        cPila--;
        cProg++;
    }

    //Compara si el elemento que hay bajo la cima de la pila es distinto que el de la cima.
    public void distinto(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if(a != b){
                pila.push((float)1);
        }else{
                pila.push((float)0);
        }
                
        cPila--;
        cProg++;
    }

    //Comprobamos el bit S y realizamos la operación de suma o resta correspondiente de los elementos que haya en la cima y bajo la cima.
    public void sumar(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        pila.push(a+b);
                
        cPila--;
        cProg++;
    }
    
        //Comprobamos el bit S y realizamos la operación de suma o resta correspondiente de los elementos que haya en la cima y bajo la cima.
    public void suma(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if (ss == false){
            pila.push(a+b);
        }else{
            pila.push(a-b);
        }
                
        cPila--;
        cProg++;
    }

    //Comprobamos el bit S y realizamos la operación de suma o resta correspondiente de los elementos que haya en la cima y bajo la cima.
    public void resta(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if (ss == false){
            pila.push(a-b);
        }else{
            pila.push(a+b);
        }
                
        cPila--;
        cProg++;
    }

    public void restar(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicrialmente, ahora en la cima
        float a = pila.pop();

        pila.push(a-b);
                
        cPila--;
        cProg++;
    }
        
    //Realizamos la operación OR con el elemento que haya en la cima  y bajo la cima.
    public void oLogica(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if(a == 1.0 || b == 1.0){
            pila.push((float) 1);
        }else{
            pila.push((float) 0);
        }

        cPila--;
        cProg++;
    }

    //Comprobamos el bit M y realizamos la operación de multiplicación o división correspondiente de los elementos que haya en la cima y bajo la cima.
    public void multiplicacion(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        if (!sm){
            pila.push(a*b);
        }else{
            // Vemos si el divisor es 0
            if(a == 0.0){
                errorByZero = true;
            }else{
                pila.push(a/b);
            }
        }

        cPila--;
        cProg++;
    }
    
    //Comprobamos el bit M y realizamos la operación de multiplicación o división correspondiente de los elementos que haya en la cima y bajo la cima.
    public void multiplicar(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        pila.push(a*b);
            
        cPila--;
        cProg++;
    }

    //Comprobamos el bit M y realizamos la operación de división o multiplicación correspondiente de los elementos que haya en la cima y bajo la cima.
    public void division(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();

        if (!sm)
            if(b == 0.0){
                errorByZero=true;
            }else{
                // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
                float a = pila.pop();
                pila.push(a/b);
            }
        else{
            // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
            float a = pila.pop();
            pila.push(a*b);
        }

        cPila--;
        cProg++;
    }

    //Realizamos la operación modulo (%) con el elemento que haya en la cima y bajo la cima.
    public void modulo(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();	

        pila.push(a%b);

        cPila--;
        cProg++;
    }

    //Realizamos la operación and (&&) con el elemento que haya en la cima y bajo la cima.
    public void yLogica(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        int c = (int)a;
        int d = (int)b;

        if(c == 1 && d == 1){
            pila.push((float)1);
        }else{
            pila.push((float)0);
        }

        cPila--;
        cProg++;
    }

    //Realizamos la operación desplazamiento a derechas (>>) con el elemento que haya en la cima  y bajo la cima.
    public void desplazaDer(){
        // Sacamos lo que hubiese en la cima
        float b = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a = pila.pop();

        int c = (int)a;
        int d = (int)b;

        pila.push((float) (c>>d));

        cPila--;
        cProg++;
    }

    //Realizamos la operación desplazamiento a izquierdas (<<) con el elemento que haya en la cima  y bajo la cima
    public void desplazaIzq(){
        // Sacamos lo que hubiese en la cima
        float b=pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        float a=pila.pop();

        int c = (int)a;
        int d = (int)b;

        pila.push((float) (c<<d));

        cPila--;
        cProg++;
    }

    //Realizamos la operación de negación (!) con el elemento que haya en la cima de la pila.
    public void negacion(){
        // Sacamos lo que hubiese en la cima
        float a = pila.pop();
        // Sacamos lo que hubiese debajo de la cima inicialmente, ahora en la cima
        int b = (int)a;

        if(b == 1){
            pila.push((float)0);
        }else{
            pila.push((float)1);
        }
        
        cProg++;
    }

    //Realizamos la operación resta de aridad uno, con el elemento que haya en la cima de la pila.
    public void menosUnario(){
        float a = pila.pop();
        pila.push(-a);
        cProg++;
    }

    //Realizamos la operación casting con el elemento que haya en la cima de la pila.
    public void casting(String tipo){
        float a = pila.pop();
        pila.push(aplicaCasting(tipo,a));
        cProg++;
    }

    //Metodo encargado de llevar a cabo el casting
    private float aplicaCasting(String tipo, float a){
        float c = 0;
        if(tipo.equals("integer") || tipo.equals("natural")){
            int b;
            b = (int)a;
            c = (float)b;
        }else if(tipo.equals("character")){
            char b;
            b = (char)a;
            c = (float)b;
        }else if(tipo.equals("float")){
            return a;
        }
        return c;			
    }

    // Metodo encargado de reservar memoria, cuando declaramos una variable
    private void reservaMemoria(int tam){
        float dir = pila.pop();
        int direccion = (int)dir;
        while(tam > 0){
            // Inicializamos la memoria con el elemento neutro
            memoria.put(direccion, (float)0.0);	
            direccion++;
            tam--;
        }
        cPila--;
        cProg++;
    }
    
    // Metodo encargado de realizar un salto en el caso de que haya un falso en la cima de la pila
    private void ir_f(int direccion){
        float num = pila.pop();
        if((int)num == 0){
            cProg = direccion;
        }else{
            cProg++;
        }
        cPila--;   	
    }
    
    // Metodo encargado de realizar un salto en el caso de que haya un verdadero en la cima de la pila
    private void ir_v(int direccion){
        float num = pila.pop();
        if((int)num == 1){
            cProg = direccion;
        }else{
            cProg++;
        }
        cPila--;   	
    }
    
    // Metodo encargado de realizar un salto incondicional
    private void ir_a(int direccion){
        cProg = direccion;
        cPila--;   	
    }
    
    // Metodo encargado de realizar un salto a la direccion que contenga la cima de la pila
    private void ir_ind(){
        float num = pila.pop();
        cProg = (int) num;
        cPila--;   	
    }
    
    // Metodo encargado copiar en las direcciones consecutivas de ,
    private void mueve(int tam){
        float a = pila.pop();
        float b = pila.pop();
        
        for(int i=0; i<tam; i++){
            memoria.put((int)b+i, memoria.get((int)a+i));
        }
        
        cProg++;
        cPila -= 2;   	
    }
}
